//  IDVI 1.0 source copyright 1996 Garth A. Dickie
//
//  This source is free for non-commercial use.  No warranty, etc.
//  Please acknowledge reuse by including the line:
//
//  "Based in part on IDVI 1.0 source copyright 1996 Garth A. Dickie"
//
//  in your documentation and source code.  For commercial use or
//  distribution, please contact the author.  Please also send
//  questions, comments, bug reports, or fixes.
//
//  Best Regards,
//  Garth A. Dickie
//  dickie@elastic.avid.com

package ibook.v10.html;

import java.util.Enumeration;
import java.util.Hashtable;
import java.io.InputStream;
import java.io.IOException;
import java.io.StringBufferInputStream;

import ibook.v10.parameter.ParameterStub;

public class HTMLTag implements ParameterStub {
    final private static int kParameterInitialSize = 3;

    private String      tag;
    private Hashtable   parameter = new Hashtable( kParameterInitialSize );

    public HTMLTag( HTMLScanner scanner ) throws HTMLFormatException, IOException {
        StringBuffer buffer = new StringBuffer( );

        if( ! ( scanner.specialCharacter && scanner.character == '<' ))
            throw new HTMLFormatException( "Missing '<' at start of tag" );

        scanner.advance( );
        skipSpace( scanner );

        tag = HTMLTag( scanner, buffer );
        skipSpace( scanner );

        while( ! ( scanner.specialCharacter && scanner.character == '>' )) {
            String key = HTMLKey( scanner, buffer );

            if( key.length( ) == 0 )
                throw new HTMLFormatException( "Expected start of parameter name, got '" + scanner.character + "'" );

            skipSpace( scanner );       

            String value;
            if( scanner.character == '=' ) {
                scanner.advance( );
                skipSpace( scanner );
                value = HTMLValue( scanner, buffer );
            } else 
                value = "";
            
            parameter.put( key, value );
            skipSpace( scanner );
        }
    }

    public HTMLTag( InputStream stream ) throws HTMLFormatException, IOException {
        this( new HTMLScanner( stream ));
    }

    public HTMLTag( String tagString ) throws HTMLFormatException, IOException {
        this( new StringBufferInputStream( tagString ));
    }

    public String toString( ) {
        StringBuffer buffer = new StringBuffer( );

        buffer.append( '<' );
        buffer.append( tag );

        Enumeration keyEnumeration = parameter.keys( );
        while( keyEnumeration.hasMoreElements( )) {
            buffer.append( ' ' );
            String key = ( String ) keyEnumeration.nextElement( );
            buffer.append( key );
            buffer.append( '=' );
            buffer.append( '"' );
            buffer.append( parameter.get( key ));
            buffer.append( '"' );
        }

        buffer.append( '>' );

        return buffer.toString( );
    }

    public String getTag( ) {
        return tag;
    }

    public String getParameter( String parameterName ) {
        return ( String ) parameter.get( parameterName.toLowerCase( ));
    }




    private static void skipSpace( HTMLScanner scanner )
            throws IOException, HTMLFormatException {

        while( Character.isSpace( scanner.character ))
            scanner.advance( );
    }

    private static String HTMLTag( HTMLScanner scanner, StringBuffer buffer )
            throws IOException, HTMLFormatException {
        
        String result;
        
        if( scanner.character == '/' ) {
            scanner.advance( );
            result = '/' + HTMLKey( scanner, buffer );
        } else
            result = HTMLKey( scanner, buffer );
        
        return result;
    }

    private static String HTMLKey( HTMLScanner scanner, StringBuffer buffer )
            throws IOException, HTMLFormatException {

        buffer.setLength( 0 );

        while(
                Character.isUpperCase( scanner.character ) ||
                Character.isLowerCase( scanner.character ) ||
                Character.isDigit( scanner.character ) ||
                scanner.character == '.' ||
                scanner.character == '-' ) {

            buffer.append( Character.toLowerCase( scanner.character ));
            scanner.advance( );
        }

        return buffer.toString( );
    }

    private static String HTMLValue( HTMLScanner scanner, StringBuffer buffer )
            throws IOException, HTMLFormatException {

        buffer.setLength( 0 );

        if( scanner.specialCharacter && scanner.character == '"' ) {
            scanner.advance( );
            while( ! ( scanner.specialCharacter && scanner.character == '"' )) {
                buffer.append( scanner.character );
                scanner.advance( );
            }
            scanner.advance( );
        } else {
            while( ! ( scanner.specialCharacter || Character.isSpace( scanner.character ))) {
                buffer.append( scanner.character );
                scanner.advance( );
            }
        }

        return buffer.toString( );
    }
}
